﻿using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FxSuperCore.Log;
using FxSuperCore.Utils;
using FxWinSuper.Functions;

namespace FxWinSuper.Util
{
	public class SimpleNamedPipelineHelper : IDisposable
	{
		private readonly string _name;
		private readonly string _end_command = $"__SimpleNamedPipelineHelperEndCommand_{Guid.NewGuid():N}__";
		private NamedPipeServerStream _pipeServer = null;
		private volatile bool _listen;
		private ManualResetEventSlim manualResetEventSlim = null;
		private ILogPrint Logger;

		public event Action<string> OnReceiveMsgEvent; 

		public SimpleNamedPipelineHelper(string name)
		{
			_name = name;
			manualResetEventSlim = new ManualResetEventSlim(false);
			Logger = new PluginLoggerPrinter($"SimpleNamedPipelineHelper:{_name}", InternalLog.Instance);
		}

		public void SendMsg(string msg)
		{
			try
			{
				NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", _name, PipeDirection.Out);
				pipeClient.Connect(1000);
				using (StreamWriter sw = new StreamWriter(pipeClient, Encoding.Default))
				{
					sw.Write(msg);
					sw.Flush();
				}
				pipeClient.Close();
			}
			catch (Exception e)
			{
				Logger.Error($"管道[{_name}]连接失败,msg:{e.Message},stack:{e.StackTrace}");
				CommonUtils.ShowWinToast("提示", $"管道[{_name}]连接失败:{e.Message}");
				return;
			}
		}

		public void StartListen()
		{
			if (_listen)
			{
				throw new Exception("管道已经处于监听状态");
			}
			_pipeServer = new NamedPipeServerStream(_name, PipeDirection.In, 1);
			_listen = true;
			Task.Run(() => HandleMsg());
			Logger.Info($"命名管道监听开启成功");
		}

		public void StopListen()
		{
			if (!_listen)
			{
				return;
			}
			_listen = false;
			try
			{
				SendMsg(_end_command);
			}
			catch (Exception)
			{
				/*ignore*/
			}
			manualResetEventSlim.Wait();
		}

		private async void HandleMsg()
		{
			if (_pipeServer == null)
			{
				return;
			}

			StreamReader sr = new StreamReader(_pipeServer, Encoding.Default);
			while (_listen)
			{
				try
				{
					await _pipeServer.WaitForConnectionAsync();
					// sr = new StreamReader(_pipeServer, Encoding.UTF8);
				}
				catch (OperationCanceledException)
				{
					Logger.Info("管道连接已取消");
					break;
				}
				catch (Exception e)
				{
					Logger.Error($"管道等待连接时发生未知错误，msg:{e.Message}, stack:{e.StackTrace}");
					break;
				}
				string msg = await sr.ReadToEndAsync();
				if (msg == _end_command)
				{
					_pipeServer.Disconnect();
					break;
				}
				OnReceiveMsgEvent?.Invoke(msg);
				_pipeServer.Disconnect();
			}
			sr.Close();
			_pipeServer.Close();
			manualResetEventSlim.Set();
		}

		public void Dispose()
		{
			_listen = false;
			_pipeServer?.Close();
			_pipeServer?.Dispose();
		}
	}
}
